using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using System.Windows.Forms;

namespace XNAStuding
{
    
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        #region Variables 
        //Shared Variables
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Vector2 mouseposition;
        Texture2D start;
        Texture2D reset;
        Rectangle setpos = new Rectangle(400, 450, 80, 30);
        Rectangle resetpos = new Rectangle(500, 450, 80, 30);

        
        public static bool started;
        
        public static Texture2D startscene;
        public static Texture2D AboutUs;

        bool mouseover = false;
        bool mouseover2 = false;
        string stepString;
        Graph Graph;
        String time = "";
        public static int delta = 0;
        //----------------------------
        //First Exp "Free Falling" 
        //------------------------
        draw Mstand;
        dragBall dragBall;
        draw standHead;
        dragStand dragStands;
        draw ball;
        //---------------------------------
        //Seconde Exp "Physical Pendulum"
        //---------------------------------
        public static Vector2 origin;
        public Vector2 screenpos;
        dragPhysical dragstand;
        dragPhysical dragphysical;      
        drawRot stand;
        int counter = 0;
        float angleInc = 0f;
        bool reach = false;
        drawRot physical;
        //----------------------
        //Third Exp " Incline "
        //----------------------
        float angle = -0.1f;
        drawRot incline;
        dragIncline draginclines;
        drawRot inclineHead;
        int blockPostion;
        int count = 0;
        bool right = true;
        //--------------------------------------------------------------------------------------------------------
        // Start Scene 
        StartScene startScene;
        public static int Experiment_No = 0;
        #endregion
        //--------------------------------------------------------------------------------------------------------
        /// <summary>
        /// Game Constractor
        /// </summary>
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            Globals.graphicsDeviceManager = graphics;
            Globals.game = this;
            Form MyGameForm = (Form)Form.FromHandle(Window.Handle);
            MyGameForm.FormBorderStyle = FormBorderStyle.None;
        }
        /// <summary>
        /// Fill the list of steps for each experiment 
        /// </summary>
        protected void DoSteps()
        {
            if (Experiment_No == 1)
            {
                Globals.Steps.Add("Drag Magntic Stand");
                Globals.Steps.Add("Drag Ball");
                Globals.Steps.Add("Press Start");
                Globals.Steps.Add("Press Change to Change height,Reset Timer and save result");
            
            }
            else if (Experiment_No == 2)
            {
                Globals.Steps.Add("Drag Stand");
                Globals.Steps.Add("Drag Pandulam");
                Globals.Steps.Add("Press Start");
                Globals.Steps.Add("Press Change to Change height,Reset Timer and save result");
            
            }
            else if (Experiment_No == 3)
            {
                Globals.Steps.Add("Drag Incline");
                Globals.Steps.Add("Press Start");
                Globals.Steps.Add("Press Change to Change the angle,Reset Timer and save result");
            
            }
        }
        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        protected override void Initialize()
        {         
            base.Initialize();
        }
        /// <summary>
        /// Allow Public access to LoadContent
        /// </summary>
        public static void load()
        {
            Globals.game.LoadContent();
        }
        /// <summary>
        /// Load Game Contents
        /// </summary>
        protected override void LoadContent()
        {
            graphics.PreferredBackBufferHeight = 600;
            graphics.PreferredBackBufferWidth = 800;
            graphics.ApplyChanges();
            this.IsMouseVisible = true;
            spriteBatch = new SpriteBatch(GraphicsDevice);
            //--------------
            //Global Values 
            //--------------
            Globals.spritePatch = this.spriteBatch;
            Globals.Background = Content.Load<Texture2D>("Back");
            Globals.font = Content.Load<SpriteFont>("Font");
            Globals.EXPfont = Content.Load<SpriteFont>("Exp");
            start = Content.Load<Texture2D>("start");
            reset = Content.Load<Texture2D>("buttonChange");
            startscene = Content.Load<Texture2D>("startSceen");
            AboutUs = Content.Load<Texture2D>("About");
            //---------------
            //Start Scene Component
            //----------------
            startScene = new StartScene(Globals.game);
            Components.Add(startScene);
            //--------------
            //Draw Tools 
            //--------------
            #region Expermint 1 tools
            if (Experiment_No == 1)
            {
                DoSteps();
                ball = new draw(this, new Rectangle(657, 454, 119, 90), new Rectangle(657, 454, 119, 90));
                Mstand = new draw(this, new Rectangle(651, 86, 125, 113), new Rectangle(651, 86, 125, 113));
                standHead = new draw(this, new Rectangle(840, 0, 200, 48), new Rectangle(65, 170, 200, 48));
                standHead.Visible = false;
                dragBall = new dragBall(Globals.game, ball, new Rectangle(standHead.posD.X + standHead.posD.Width - 50, standHead.posD.Y + standHead.posD.Height, 33, 38), new Rectangle(1000, 50, 33, 38));
                dragStands = new dragStand(Globals.game, Mstand, new Rectangle(60, 110, 62, 390), new Rectangle(840, 50, 62, 390), standHead, ball);
                Components.Add(dragBall);
                Components.Add(dragStands);
                Graph = new Graph(1);
            }
            #endregion 
            #region Expermint 2 tools
            else if (Experiment_No == 2)
            {
                DoSteps();
                origin = new Vector2(33,18);
                stand = new drawRot(this, new Rectangle(657, 329, 43, 104), new Rectangle(657, 329, 43, 104), 0f, new Vector2(0, 0));
                physical = new drawRot(this, new Rectangle(725, 334, 44, 99), new Rectangle(758, 352, 44, 99), angleInc, origin);
                dragstand = new dragPhysical(Globals.game, stand, new Rectangle(217, 100, 82, 396), new Rectangle(918, 97, 85, 403));
                dragphysical = new dragPhysical(Globals.game, physical, new Rectangle(265, 120, 62, 359), new Rectangle(1003, 100, 66, 301));
                Components.Add(dragstand);
                Components.Add(dragphysical);
                Graph = new Graph(2);
            }
            #endregion
            #region Expermint 3 tools
            else if (Experiment_No == 3)
            {
                blockPostion = 533;
                DoSteps();
                incline = new drawRot(this, new Rectangle(651, 214, 129, 103), new Rectangle(651, 214, 129, 103), 0, new Vector2(0, 0));
                inclineHead = new drawRot(this, new Rectangle(533, 671, 496, 55), new Rectangle(76, 418, 496, 55), angle, new Vector2(0, 55));
                draginclines = new dragIncline(Globals.game, incline, new Rectangle(30, 30, 400, 400), new Rectangle(8, 639, 484, 88), inclineHead);
                Components.Add(draginclines);
                Graph = new Graph(3);
            }
            #endregion
        }
        /// <summary>
        /// Allow Public access to UnloadContents
        /// </summary>
        public static void ClearComponants()
        {
            Globals.game.UnloadContent();
        }
        /// <summary>
        /// Unload all Game Data and lists
        /// </summary>
        protected override void UnloadContent()
        {
            for (int i = 0; i < Components.Count; i++)
            {
                Components.RemoveAt(i);
                i--;
            }
            Globals.Steps.Clear();
            Globals.t.stop();
            Globals.t.go = false;
            Globals.step = 0;
        }
        #region Game Logic
        /// <summary>
        /// Exp1 Logic 
        /// </summary>
        protected void Exp1Logic()
        {
            int startPos = ball.posD.Y + ball.posD.Height;
            if (startPos < 500)
            {
                //Globals.step = 3;
                Globals.t.increase();
                startPos += 1;
                ball.posD.Y += 1;
                dragBall.Enabled = false;
                mouseover = true;

            }
            else
            {
               
                //Globals.step = 2;
                Globals.step = 3;
                Globals.t.go = false;
                mouseover = false;
                
            }
        }
        /// <summary>
        /// Exp2 Logic 
        /// </summary>
        public void Exp2Logic()
        {
            
            if (counter <= 19)
            {
                if ((physical.rot > MathHelper.ToRadians(20) || physical.rot < MathHelper.ToRadians(-20)))
                {
                    reach = !reach;
                    counter++;
                }
                if (reach)
                {
                    physical.rot -= MathHelper.ToRadians(physical.v.Y/100);
                   
                }
                else
                {
                    physical.rot += MathHelper.ToRadians(physical.v.Y / 100);
                   
                }
                
                Globals.t.increase();
            }
            else
            {
                Globals.step = 3;
                Globals.t.go = false;
                mouseover = false;
            }

        }
        /// <summary>
        /// Exp3 Logic
        /// </summary>
        public void Exp3Logic()
        {

            if (blockPostion <= 940)
            {
                Globals.t.increase();
                inclineHead.posTex = new Rectangle(blockPostion += (int)(10 * Math.Abs(inclineHead.rot)), 671, 496, 55);
            }
            else
            {
                mouseover = false;
                Globals.step = 2;
            }
        }    
        #endregion
        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            Rectangle mouseRec = new Rectangle((int)mouseposition.X, (int)mouseposition.Y, 1, 1);
            MouseState mouse_state = Mouse.GetState();
            mouseposition.X = mouse_state.X;
            mouseposition.Y = mouse_state.Y;
            time=Globals.t.drawTimer();

            if (Experiment_No == 1)
            {
                //start
                stepString = Globals.Steps[Globals.step];
                if (Globals.step > 1 && mouseRec.Intersects(setpos) && mouse_state.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
                {
                    mouseover = true;
                }
                if (mouseover)
                {
                    Exp1Logic();
                    Globals.t.go = true;
                }

                //change
                if (Globals.step == 3 && resetpos.Intersects(mouseRec) && mouse_state.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
                {
                    mouseover2 = true;
                }
                if (mouseover2)
                {
                    mouseover2 = false;
                    if (standHead.posD.Y < 400)
                        standHead.posD.Y = standHead.posD.Y + 21;
                    ball.posD.Y = ball.posD.Y + 21;
                    dragBall.Enabled = false;
                    ball.posD = new Rectangle(standHead.posD.X + standHead.posD.Width - 50, standHead.posD.Y + standHead.posD.Height, 33, 38);
                    int stepTime = Globals.t.msec + Globals.t.sec * 1000 + Globals.t.min * 60000;
                    Graph.point(stepTime, (100 - delta));
                    if (delta == 30)
                        Graph.Show();
                    Globals.t.stop();
                    Globals.step = 2;
                    delta += 5;
                  }
            }
            if (Experiment_No == 2)
            {
                stepString = Globals.Steps[Globals.step];
                if (right)
                {
                    if (stand.posD.X == 217 && stand.posD.Y == 100)
                    {
                        Globals.step = 1;
                        if (physical.posD.X == 265 && stand.posD.X == 217 && stand.posD.Y == 100)
                        {
                            Globals.step = 2;
                        }
                    }
                    else
                        Globals.step = 0;
                }

                if (Globals.step > 1 && mouseRec.Intersects(setpos) && mouse_state.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
                {
                    mouseover = true;
                }
                if (mouseover)
                {
                    Globals.t.go = true;
                    Exp2Logic();
                    right = false;
                }
                //change
                if (resetpos.Intersects(mouseRec) && mouse_state.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed && Globals.step == 3)
                {
                    mouseover2 = true;
                }
                if (mouseover2)
                {
                    physical.rot = 0;
                    mouseover2 = false;
                    if (physical.v.Y <100)
                    {
                        physical.v.Y += 26;
                        float H= physical.posTex.Height - physical.v.Y;
                        int T = (Globals.t.msec + Globals.t.sec * 1000 + Globals.t.min * 60000)/10;
                        Graph.point(H*H, H*T);
                    }
                    else
                        Graph.Show();
                    Globals.t.stop();
                    counter = 0;
                    Globals.step = 2;
                }
            }
            if (Experiment_No == 3)
            {
                stepString = Globals.Steps[Globals.step];
                //start
                if (mouseRec.Intersects(setpos) && mouse_state.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
                {
                    mouseover = true;
                }
                if (mouseover)
                {
                    Exp3Logic();
                    Globals.t.go = true;
                }
                //change
                if (Globals.step == 2 && resetpos.Intersects(mouseRec) && mouse_state.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
                {
                    count++;
                    mouseover2 = true;
                }
                if (mouseover2)
                {
                    mouseover2 = false;
                    inclineHead.rot += (-0.05f);
                    angle = inclineHead.rot;
                    inclineHead.posTex.X = 533;
                    blockPostion = 533;
                    double stepTime = Globals.t.msec + Globals.t.sec * 1000 + Globals.t.min * 60000;
                     Graph.point((Math.Sin(MathHelper.ToDegrees(angle))), (2 * 496) / (Math.Pow(stepTime, 2)));

                    if (delta >= 30)
                        Graph.Show(); 
                    

                    Globals.t.stop();
                    Globals.step = 1;
                    delta += 5;
                }
            }
            base.Update(gameTime);
        }
        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            Color x = new Color(214, 226, 237);
            GraphicsDevice.Clear(x);
            spriteBatch.Begin();

            if (Experiment_No == 1)
            {
                
                spriteBatch.Draw(Globals.Background, new Vector2(graphics.GraphicsDevice.Viewport.X, graphics.GraphicsDevice.Viewport.Y), Color.White);
                spriteBatch.DrawString(Globals.EXPfont, "Free Falling", new Vector2(200, 30), Color.Black);
                spriteBatch.DrawString(Globals.font, " Step " + (Globals.step + 1).ToString() + " " + Globals.Steps[Globals.step].ToString(), new Vector2(55, 550), Color.Black);
                //spriteBatch.DrawString(Globals.font, stepString, new Vector2(75, 550), Color.Black);
                spriteBatch.DrawString(Globals.font, "StopWatch", new Vector2(450, 100), Color.Black);

                if (Globals.step >= 2)
                {
                    spriteBatch.DrawString(Globals.font, "Distance", new Vector2(380, 280), Color.Black);
                    int dist = 500 - standHead.posD.Y + standHead.posD.Height;

                    spriteBatch.DrawString(Globals.font, (100 - delta).ToString(), new Vector2(500, 280), Color.Black);
                }
                spriteBatch.DrawString(Globals.font, time, new Vector2(455, 120), Color.Black);
              
                if (Globals.step > 1)
                {
                    spriteBatch.Draw(start, setpos, Color.White);
                }
                if (Globals.step == 3)
                {

                    spriteBatch.Draw(reset, resetpos, Color.White);

                }
            }
            if (Experiment_No == 2)
            {
                spriteBatch.Draw(Globals.Background, new Rectangle(0, 0, graphics.GraphicsDevice.Viewport.Width, graphics.GraphicsDevice.Viewport.Height), new Rectangle(0, 0, 800, 600), Color.White);
                spriteBatch.DrawString(Globals.EXPfont, "Physical Pendulum", new Vector2(150, 30), Color.Black);
                spriteBatch.DrawString(Globals.font, "StopWatch", new Vector2(450, 100), Color.Black);
                spriteBatch.DrawString(Globals.font, time, new Vector2(455, 120), Color.Black);
                spriteBatch.DrawString(Globals.font, " Step " + (Globals.step + 1).ToString() + " " +Globals.Steps[Globals.step].ToString(), new Vector2(55, 550), Color.Black);
                
                spriteBatch.DrawString(Globals.font, "Length : " + (physical.posTex.Height - physical.v.Y).ToString(), new Vector2(430, 380), Color.Black);
                if (Globals.step == 2 && stand.posD.X == 217 && stand.posD.Y == 100 && physical.posD.X == 265)
                    spriteBatch.Draw(start, setpos, Color.White);
                if (Globals.step == 3)
                    spriteBatch.Draw(reset, resetpos, Color.White);
            }
            if (Experiment_No == 3)
            {
                spriteBatch.Draw(Globals.Background, new Vector2(graphics.GraphicsDevice.Viewport.X, graphics.GraphicsDevice.Viewport.Y), Color.White);
                spriteBatch.DrawString(Globals.EXPfont, "Inclined Plane Motion", new Vector2(150, 30), Color.Black);
                spriteBatch.DrawString(Globals.font, " Step " + (Globals.step + 1).ToString() + " " + Globals.Steps[Globals.step].ToString(), new Vector2(55, 550), Color.Black);

                spriteBatch.DrawString(Globals.font, "StopWatch", new Vector2(450, 100), Color.Black);
                if (Globals.step >= 1)
                {
                    spriteBatch.DrawString(Globals.font, "Angel Is : ", new Vector2(100, 100), Color.Black);
                    spriteBatch.DrawString(Globals.font, (Math.Abs(MathHelper.ToDegrees(angle))).ToString(), new Vector2(195, 100), Color.Black);
                }
                spriteBatch.DrawString(Globals.font, time, new Vector2(455, 120), Color.Black);
             
                if (Globals.step == 1)
                    spriteBatch.Draw(start, setpos, Color.White);
                if (Globals.step == 2)
                    spriteBatch.Draw(reset, resetpos, Color.White);
            }
            
         
            spriteBatch.End();
            base.Draw(gameTime);
            
        }
    }
}
